package cn.huixh.blindbox.service.impl;

import cn.huixh.blindbox.exception.impl.BizException;
import cn.huixh.blindbox.mapper.AccountMapper;
import cn.huixh.blindbox.mapper.FileMapper;
import cn.huixh.blindbox.pojo.bo.AccountFileBO;
import cn.huixh.blindbox.pojo.po.Account;
import cn.huixh.blindbox.service.FileService;
import cn.huixh.blindbox.utils.ToolsUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.Optional;

/**
 * @author huixh
 * @version 1.0
 * @date 2022/5/10 10:32
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class FileServiceImpl extends ServiceImpl< FileMapper, cn.huixh.blindbox.pojo.po.File > implements FileService {

    private final ToolsUtil toolsUtil;

    private final AccountMapper accountMapper;

    private final cn.huixh.blindbox.utils.FileUtil fileUtil;

    @Value("${file.upload.path}")
    private String rootPath;
    @Value("${spring.application.name}")
    private String projectName;

    /**
     * 文件校验
     *
     * @param bytes 文件字节数组
     * @param md5   文件md5
     */
    @Override
    public void fileVerify(byte[] bytes, String md5) {
        String fileMd5 = toolsUtil.getFileMd5(bytes);
        if (!StrUtil.equals(fileMd5, md5)) {
            throw new BizException("文件md5校验失败");
        }
    }

    /**
     * 文件上传
     *
     * @param accountFileBO 账户文件信息
     */
    @Override
    public void uploadFile(AccountFileBO accountFileBO) {
        File file = toolsUtil.transferToFile(accountFileBO.getFile());
        Optional< Account > opt = Optional.ofNullable(accountMapper.selectById(accountFileBO.getAccountId()));
        opt.ifPresentOrElse(account -> {
            Optional< cn.huixh.blindbox.pojo.po.File > optional = Optional.ofNullable(
                    this.getBaseMapper().selectOne(
                            new QueryWrapper< cn.huixh.blindbox.pojo.po.File >()
                                    .eq("file_name", accountFileBO.getFile().getOriginalFilename())
                                    .eq("account_id", accountFileBO.getAccountId())
                                    .eq("md5", accountFileBO.getMd5()))
            );

            if (optional.isPresent()) {
                accountFileBO.setFileId(optional.get().getId());
                return;
            }

            String filePath = rootPath + "\\" + projectName + "\\" + account.getEmail() + "\\";

            var fileBean = cn.huixh.blindbox.pojo.po.File.builder()
                    .fileName(accountFileBO.getFile().getOriginalFilename())
                    .createAuthor(account.getEmail())
                    .fileType(accountFileBO.getFile().getContentType())
                    .md5(accountFileBO.getMd5())
                    .accountId(account.getId())
                    .filePath(filePath)
                    .build();
            save(fileBean);
            accountFileBO.setFileId(fileBean.getId());
            fileUtil.uploadFile(filePath, accountFileBO.getFile().getOriginalFilename(), file);
        }, () -> {
            throw new BizException("账户不存在无法上传文件");
        });
    }

    /**
     * 文件下载
     *
     * @param accountFileBO 账户文件信息
     */
    @Override
    public File downloadFile(AccountFileBO accountFileBO) {
        var opt = Optional.ofNullable(getBaseMapper().selectOne(new QueryWrapper< cn.huixh.blindbox.pojo.po.File >().lambda()
                .eq(cn.huixh.blindbox.pojo.po.File::getId, accountFileBO.getFileId())
        ));
        if (opt.isPresent()) {
            var file = opt.get();
            return fileUtil.getFile(file.getFilePath(), file.getFileName());
        }
        throw new BizException("文件不存在");
    }

    /**
     * 文件删除
     *
     * @param accountId 账户id
     * @param fileId    文件id
     */
    @Override
    public void deleteFile(String accountId, String fileId) {
        var file = getById(fileId);
        Assert.notNull(file, "文件不存在");
        Assert.isTrue(file.getAccountId().equals(accountId), "文件不属于该账户");

        removeById(file);
    }
}
